from fastapi import Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession

from basic.database import get_db
from basic.s3 import S3
from .interfaces import IFileService
from .repository.fileRepository import create_file, get_file, update_file, delete_file, link_file_to_entry
from .repository.versionRepository import get_versions


class FileService(IFileService):
    def __init__(self, db: AsyncSession = Depends(get_db), s3: S3 = Depends(S3)):
        self.db = db
        self.s3 = s3

    async def create_file(self, repo_key: str, file_name: str, object_key: str):
        """
        创建文件，并关联到版本
        
        Args:
            repo_key: 仓库键
            file_name: 文件名
            object_key: 文件对象键（用作entry_key）
            
        Returns:
            新文件信息
        """
        try:
            async with self.db.begin():
                # 创建文件并关联到条目
                new_file = await create_file(self.db, file_name, object_key)
                
                # 提交事务
                await self.db.commit()
            
            return {"file_key": new_file.key}
        except Exception as e:
            await self.db.rollback()
            print(f"创建文件错误: {e}")
            raise HTTPException(status_code=500, detail=f"创建文件失败: {str(e)}")

    async def update_file(self, repo_key: str, file_key: str, update_key: str, update_value: str):
        """
        更新文件信息
        
        Args:
            repo_key: 仓库键
            file_key: 文件键
            update_key: 要更新的键
            update_value: 要更新的值
            
        Returns:
            更新后的文件信息
        """
        try:
            async with self.db.begin():
                # 验证文件是否存在
                file = await get_file(self.db, file_key)
                if not file:
                    raise HTTPException(status_code=404, detail="文件不存在")
                
                # 更新文件
                if update_key == "name":
                    updated_file = await update_file(self.db, file_key, update_value)
                    if not updated_file:
                        raise HTTPException(status_code=500, detail="更新文件失败")
                else:
                    raise HTTPException(status_code=400, detail=f"不支持更新字段: {update_key}")
                
                await self.db.commit()
            
            return {"file_key": file_key}
        except HTTPException:
            raise
        except Exception as e:
            await self.db.rollback()
            print(f"更新文件错误: {e}")
            raise HTTPException(status_code=500, detail=f"更新文件失败: {str(e)}")
    
    async def metadata(self, repo_key: str, file_key: str):
        """
        获取文件元数据，包括版本列表
        
        Args:
            repo_key: 仓库键
            file_key: 文件键
            
        Returns:
            文件元数据
        """
        try:
            # 获取文件信息
            file = await get_file(self.db, file_key)
            if not file:
                raise HTTPException(status_code=404, detail="文件不存在")
            
            # 构建响应数据
            response = {
                "file_name": file.name,
                "file_key": file.key,
                "download_url": self.s3.presigned_download_url(repo_key, file.key)
            }
            
            return response
        except HTTPException:
            raise
        except Exception as e:
            print(f"获取文件信息错误: {e}")
            raise HTTPException(status_code=500, detail=f"获取文件信息失败: {str(e)}")

    async def delete_file(self, repo_key: str, file_key: str):
        """
        删除文件
        
        Args:
            repo_key: 仓库键
            file_key: 文件键
            
        Returns:
            删除的文件键
        """
        try:
            async with self.db.begin():
                # 验证文件是否存在
                file = await get_file(self.db, file_key)
                if not file:
                    raise HTTPException(status_code=404, detail="文件不存在")
                
                # 删除文件及其关联
                result = await delete_file(self.db, file_key)
                if not result:
                    raise HTTPException(status_code=500, detail="删除文件失败")

                await self.db.commit()
            
            return {"file_key": file_key}
        except HTTPException:
            raise
        except Exception as e:
            await self.db.rollback()
            print(f"删除文件错误: {e}")
            raise HTTPException(status_code=500, detail=f"删除文件失败: {str(e)}")
            
    async def link_file_to_entry(self, file_key: str, entry_key: str) -> bool:
        """
        将文件关联到条目
        
        Args:
            file_key: 文件键
            entry_key: 条目键
            
        Returns:
            是否成功关联
        """
        try:
            # 验证文件是否存在
            file = await get_file(self.db, file_key)
            if not file:
                return False
                
            # 关联文件到条目
            result = await link_file_to_entry(self.db, file_key, entry_key)
            await self.db.commit()
            return result
        except Exception as e:
            await self.db.rollback()
            print(f"关联文件到条目错误: {e}")
            return False

